#include <math.h>
#include <iostream>
#include <map>
#include <string>
#include <utility>

using std::cout;
using std::endl;
using std::multimap;
using std::string;
using std::pair;
using std::make_pair;

template <typename Container>
void display(const Container &con)
{
    for(auto &elem : con)
    {
        cout << elem.first << "  " << elem.second << endl;
    }
}

void test()
{
    //multimap的特征
    //1、multimap中存放的是pair，也就是key-value类型，key值是不唯一
    //的，可以重复，value是可以重复的,也可以不重复
    //2、默认情况下，也会按照key值进行升序排列
    //3、底层实现也是使用的红黑树
    //
    multimap<int, string> number = {
    /* multimap<int, string, std::greater<int>> number = { */
        pair<int, string>(8, "wuhan"),
        pair<int, string>(6, "wuhan"),
        pair<int, string>(9, "hubei"),
        {1, "beijing"},
        {1, "dongjing"},
        {2, "nanjing"},
        make_pair(3, "tianjin"),
        make_pair(8, "wuhan"),
        make_pair(10, "shenzhen")
    };
    display(number);

    cout << endl << "multimap的查找操作" << endl;
    size_t cnt = number.count(8);
    cout << "cnt = " << cnt << endl;

    cout << endl;
    multimap<int, string>::iterator it = number.find(10);
    if(it == number.end())
    {
        cout << "该元素不存在multimap中" << endl;
    }
    else
    {
        cout << "该元素存在multimap中 " 
             << it->first << "  "
             << it->second << endl;
    }

    cout << endl << "multimap的insert操作" << endl;
    /* number.insert(pair<int, string>(4, "chongqing")); */
    /* number.insert({4, "chongqing"}); */
    number.insert(make_pair(4, "chongqing"));
    display(number);

    cout << endl << endl;
    multimap<int, string> number2 = {
        {7, "sichuan"},
        {5, "sichuan"},
    };
    number.insert(number2.begin(), number2.end());
    display(number);

    cout << endl << endl;
    number.insert({ {11, "hello"}, {2, "nanjing"}, {13, "hangzhou"} });
    display(number);

    cout << endl << "multimap的下标操作" << endl;
    //multimap中key值是可以重复的，所以不支持下标，因为key值相同
    //value可以不一样，就会产生二义性
    /* cout << "number[1] = " << number[1] << endl;//error */
    /* cout << "number[12] = " << number[12] << endl;//error */
    display(number);
}

class Point
{
public:
    Point(int ix = 0, int iy = 0)
    : _ix(ix)
    , _iy(iy)
    {
    }

    double getDistance() const
    {
        return hypot(_ix, _iy);
    }

    void print() const
    {
        cout << "(" << _ix 
             << ", " << _iy
             << ")";
    }

    int getX() const
    {
        return _ix;
    }

    int getY() const
    {
        return _iy;
    }

    ~Point()
    {
    }

    friend std::ostream &operator<<(std::ostream &os, const Point &rhs);

private:
    int _ix;
    int _iy;
};

std::ostream &operator<<(std::ostream &os, const Point &rhs)
{
    os << "(" << rhs._ix 
       << ", " << rhs._iy
       << ")";

    return os;
}

void test2()
{
    /* multimap<Point, string> number = {//error */
    multimap<string, Point> number = {
        {"hello", Point(1, 2)},
        {"world", Point(2, 2)},
        make_pair("wuhan", Point(3, 2)),
        make_pair("wuhan", Point(3, 2)),
        {"nanjing", Point(1, 2)},
        {"dongjing", Point(1, 2)},
    };
    display(number);
}
int main(int argc, char **argv)
{
    test2();
    return 0;
}

